package main

import "fmt"

type Bitmap struct {
	data []uint8
}

func set(bitmap *Bitmap, pos int) {
	// 要将某个位置的二进制设置为1，计算当前切片是否需要扩容
	requiredBits := pos - (len(bitmap.data)<<3 - 1)

	// 若requiredBits大于0，代表需要扩容
	if requiredBits > 0 {
		// 调用扩容函数
		expandBitmap(bitmap, requiredBits)
	}

	// 将pos右移3位，代表除以8，可以找到uint8切片中的对应索引
	elementIndex := pos >> 3

	// 设置对应位置二进制数为1
	bitmap.data[elementIndex] = bitmap.data[elementIndex] | 1<<(pos%8)
}

func checkPos(bitmap *Bitmap, pos int) {
	// 如果要获取的pos位置，已经超出了当前容量，则该pos位置未设置
	if pos-(len(bitmap.data)<<3) > 1 {
		fmt.Println(pos, "是否存在：", false)
		return
	}

	// pos位置右移3位，代表除以8，可以找到uint8切片中的对应索引
	elementIndex := pos >> 3
	// 1<< (pos%8)，将1左移pos%8，然后与uint8切片中的uint8进行&操作，得到该位置是否为1
	setting := bitmap.data[elementIndex]&(1<<(pos%8)) > 0

	fmt.Println(pos, "是否存在：", setting)
}

func expandBitmap(bitmap *Bitmap, space int) {
	// 扩展时，需要多少个unit8进行存储
	element2Expand := (space + 7) >> 3

	// 创建新的切片，并复制原有数据
	newData := make([]uint8, element2Expand+len(bitmap.data))
	copy(newData, bitmap.data)

	// 将bitmap的data属性，设置为新的切片
	bitmap.data = newData
}

func main() {
	bitmap := new(Bitmap)
	set(bitmap, 64)
	checkPos(bitmap, 63)
	checkPos(bitmap, 64)
}
